package com.rocpenghua.excel.utils;

import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * excel处理工具
 * 概念-> 表头数据:报表的表头
 * 行内数据:表头以下的数据
 * 功能:动态生成单级，多级Excel表头
 * 备注：tree型结构数据的root节点的id必须为零（0）
 *
 * @param <T>
 */
public class XssfExcelTool<T> extends ExcelTool<T> {

    /**
     * 无参数 初始化 对象
     */
    public XssfExcelTool() {
        this.title = "sheet1";
        this.workbook = new XSSFWorkbook();
        init(0);
    }

    /**
     * 有参数 初始化 对象
     *
     * @param title
     * @param colWidth
     * @param rowHeight
     * @param dateFormat
     */
    public XssfExcelTool(String title, int colWidth, int rowHeight, String dateFormat) {
        this.colWidth = colWidth;
        this.rowHeight = rowHeight;
        this.title = title;
        this.workbook = new XSSFWorkbook();
        this.sdf = new SimpleDateFormat(dateFormat);
        init(0);
    }

    public XssfExcelTool(String title, int colWidth, int rowHeight) {
        this.colWidth = colWidth;
        this.rowHeight = rowHeight;
        this.title = title;
        this.workbook = new XSSFWorkbook();
        init(0);
    }

    public XssfExcelTool(String title, int colWidth, int rowHeight, int flag) {
        this.colWidth = colWidth;
        this.rowHeight = rowHeight;
        this.title = title;
        this.workbook = new XSSFWorkbook();
        init(flag);
    }

    public XssfExcelTool(String title) {
        this.title = title;
        this.workbook = new XSSFWorkbook();
        init(0);
    }

    /**
     * ExcelTool 属性 get、set 方法 结束
     */
    //内部统一调用的样式初始化
    @Override
    protected void init(int styleFlag) {
        this.styleTitle = this.workbook.createCellStyle();
        this.styleTitle.setAlignment(HorizontalAlignment.LEFT);
        this.styleTitle.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        this.styleTitle.setRightBorderColor(IndexedColors.BLACK.getIndex());
        this.styleTitle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        Font font = this.workbook.createFont();
        font.setFontHeightInPoints((short) 16);//设置字体大小
        font.setBold(true);
        font.setFontName("宋体");
        this.styleTitle.setFont(font);

        this.styleHead = this.workbook.createCellStyle();
        this.styleHead.setAlignment(HorizontalAlignment.CENTER);// 左右居中
        this.styleHead.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
        this.styleHead.setRightBorderColor(IndexedColors.BLACK.getIndex());
        this.styleHead.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        Font font1 = this.workbook.createFont();
        font1.setBold(true);
        font1.setFontName("宋体");
        this.styleHead.setFont(font1);
        this.styleHead.setWrapText(true);

        Font font2 = this.workbook.createFont();
        font2.setFontName("宋体");
        switch (styleFlag) {
            case 1:
                this.styleBody = this.workbook.createCellStyle();
                this.styleBody.setAlignment(HorizontalAlignment.LEFT);
                this.styleBody.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
                this.styleBody.setRightBorderColor(IndexedColors.BLACK.getIndex());
                this.styleBody.setBottomBorderColor(IndexedColors.BLACK.getIndex());
                this.styleBody.setBorderRight(BorderStyle.valueOf((short) 1));// 边框的大小
                this.styleBody.setBorderBottom(BorderStyle.valueOf((short) 1));// 边框的大小
                this.styleBody.setFont(font2);
                break;
            default:
                this.styleBody = this.workbook.createCellStyle();
                this.styleBody.setAlignment(HorizontalAlignment.CENTER);
                this.styleBody.setVerticalAlignment(VerticalAlignment.CENTER);// 上下居中
                this.styleBody.setRightBorderColor(IndexedColors.BLACK.getIndex());
                this.styleBody.setBottomBorderColor(IndexedColors.BLACK.getIndex());
                this.styleBody.setBorderRight(BorderStyle.valueOf((short) 1));// 边框的大小
                this.styleBody.setBorderBottom(BorderStyle.valueOf((short) 1));// 边框的大小
                this.styleBody.setFont(font2);
                break;
        }
    }


    /**
     * 根据list 来创建单元格 暂时没有用
     *
     * @param row
     * @param j
     * @param finame
     * @param t
     */
    @Override
    public void createColl(Row row, int j, String finame, T t) {
        XSSFCell cell = (XSSFCell) row.createCell(j);  //创建单元格
        cell.setCellStyle(this.styleBody); //设置单元格样式
        String text = "";
        if (t instanceof List) {
            List<Map> temp = (List<Map>) t;
            if (j >= temp.size()) {
                return;
            }
            text = String.valueOf(temp.get(j).get(finame) == null ? "" : temp.get(j).get(finame));
        }
        XSSFRichTextString richString = new XSSFRichTextString(text);
        cell.setCellValue(richString);
    }

    /**
     * 创建单元格
     *
     * @param row         Excel对应的行
     * @param tpamscolumn 当前单元格对象
     * @param v
     * @param colNum
     * @param rowNum
     * @throws Exception
     */
    @Override
    public void createCol(Row row, Column tpamscolumn, T v, int rowNum, int colNum) throws Exception {
        XSSFCell cell = (XSSFCell) row.createCell(tpamscolumn.getCol());  //创建单元格
        cell.setCellStyle(this.styleBody); //设置单元格样式
        final Object[] value = {null};
        if (v instanceof Map) {
            Map<String, Object> m = (Map) v;
            for (Map.Entry<String, Object> entry : m.entrySet()) {
                if (entry.getKey().equals(tpamscolumn.getFieldName()) && !tpamscolumn.isHasChilren()) {
                    value[0] = entry.getValue();
                }
            }

        } else {
            Class<?> cls = v.getClass();// 拿到该类
            Field[] fields = cls.getDeclaredFields();// 获取实体类的所有属性，返回Field数组
            for (int i = 0; i < fields.length; i++) {
                Field f = fields[i];
                //f.setAccessible(true); // 设置些属性是可以访问的
                if (tpamscolumn.getFieldName().equals(f.getName()) && !tpamscolumn.isHasChilren()) {
                    value[0] = f.get(v);
                }
                if (value[0] instanceof Date) {
                    value[0] = parseDate((Date) value[0]);
                }
            }
        }
        if (value[0] != null) {
            XSSFRichTextString richString = new XSSFRichTextString(value[0].toString());
            cell.setCellValue(richString);
        }

    }

    /**
     * 使用递归 在excel写入表头数据 支持单级，多级表头的创建
     *
     * @param listTpamscolumn 表头数据
     * @param sheetCo         哪个分页
     * @param rowIndex        当前Excel的第几行
     */
    @Override
    public void createHead(List<Column> listTpamscolumn, Sheet sheetCo, int rowIndex) {
        XSSFRow row = (XSSFRow) sheetCo.getRow(rowIndex);
//        if(row == null)row = sheetCo.createRow(rowIndex);
        int len = listTpamscolumn.size();//当前行 有多少列
        for (int i = 0; i < len; i++) {//i是headers的索引，n是Excel的索引 多级表头
            Column tpamscolumn = listTpamscolumn.get(i);
            //创建这一行的第几列单元格
            int r = tpamscolumn.getRow();
            int rLen = tpamscolumn.getrLen();
            int c = tpamscolumn.getCol();
            int cLen = tpamscolumn.getcLen();
            int endR = r + rLen;
            int endC = c + cLen;
            if (endC > c) {
                endC--;
            }
            XSSFCell cell = row.getCell(c);
//            if( null == cell)cell = row.createCell(c);

            XSSFRichTextString text = new XSSFRichTextString(tpamscolumn.getContent());
            if (rowIndex == 0) {
                cell.setCellStyle(this.styleTitle); //设置表头样式
            } else {
                cell.setCellStyle(this.styleHead); //设置表头样式
            }
            cell.setCellValue(text);
            // 合并单元格
            CellRangeAddress cra = new CellRangeAddress(r, endR, c, endC);
            sheetCo.addMergedRegion(cra);

            // 使用RegionUtil类为合并后的单元格添加边框
            RegionUtil.setBorderBottom(BorderStyle.valueOf((short) 1), cra, sheetCo); // 下边框
            RegionUtil.setBorderLeft(BorderStyle.valueOf((short) 1), cra, sheetCo); // 左边框
            RegionUtil.setBorderRight(BorderStyle.valueOf((short) 1), cra, sheetCo); // 有边框

            if (tpamscolumn.isHasChilren()) {
                rowIndex = r + 1;
                createHead(tpamscolumn.getListTpamscolumn(), sheetCo, rowIndex);
            }
        }
    }
}
